/**
 * 百度文心ernie-3.5-8k模型请求解析插件
 *
 * 【插件开发规范】
 * 1. 插件必须导出一个class，class名称建议与文件名一致。
 * 2. 必须实现 getRequestParseRule(rawRequest) 和 getResponseParseRule(rawResponse) 方法（如有）。
 * 3. 若插件需要自定义请求（如API签名、特殊协议），可实现 async makeRequest(rawRequest, callback) 方法（full模式）。
 * 4. 若插件遇到API错误（如返回error字段、HTTP异常），必须主动调用 callback(new Error(...), null)。
 *    - 这样主程序才能捕获并弹窗，便于排查问题。
 *    - 切勿只打印日志或吞掉异常。
 * 5. 若API返回结构中有 error 字段，务必检测并 callback(new Error(...), null)。
 * 6. 插件开发完成后，建议多测试异常场景，确保错误能被准确弹窗。
 * 7. 插件可通过 this.httpClient 访问主程序注入的 httpClient（如需自定义请求）。
 * 8. 流式模式下，callback多次回调内容，遇到异常也需 callback(err, null)。
 */

module.exports = class ErnieRequestParserPlugin {
  /**
   * 构造函数 - 沙盒适配版本
   * @param {Object} options - 插件初始化参数，httpClient由沙盒系统注入
   */
  constructor(options = {}) {
    this.name = 'ErnieRequestParserPlugin';
    
    // 从沙盒注入的能力中获取HTTP客户端
    this.httpClient = options.httpClient;
    
    console.log('[ErniePlugin] 沙盒模式初始化', {
      hasHttpClient: !!this.httpClient,
      mode: 'full-request'
    });
    
    // 验证HTTP客户端能力
    if (!this.httpClient) {
      console.warn('[ErniePlugin] httpClient 未注入，将使用默认实现');
      this.httpClient = {
        request: async (url, options) => {
          throw new Error('[ErniePlugin] httpClient未正确注入，无法发起网络请求');
        }
      };
    }
    
    if (typeof this.httpClient.request !== 'function') {
      throw new Error('[ErniePlugin] httpClient必须实现request方法');
    }
  }

  /**
   * 动态设置HTTP客户端（支持向后兼容）
   */
  setHttpClient(httpClient) {
    if (httpClient && typeof httpClient.request === 'function') {
      this.httpClient = httpClient;
      console.log('[ErniePlugin] HTTP客户端已更新');
    } else {
      console.warn('[ErniePlugin] 提供的httpClient无效');
    }
  }

  /**
   * 插件主入口：发起模型请求【标准代码，勿动】
   * @param {Object} rawRequest - 主程序传入的请求参数
   * @param {Function} callback - 回调函数，流式多次/非流式一次
   */
  async makeRequest(rawRequest = {}, callback) {
    // === 参数校验【标准代码，勿动】 ===
    if (!callback || typeof callback !== 'function') {
      throw new Error('必须提供有效的callback函数');
    }
    // === 业务参数解析【需适配】 ===
    // 如需适配其他模型/接口，只需修改此处的 requestUrl 与 requestOptions 生成逻辑
    const requestUrl = `${rawRequest.base_url}${rawRequest.endpoint}`; // 【需适配】接口URL拼接逻辑
    const requestOptions = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${rawRequest.api_key}` // 【需适配】鉴权方式
      },
      body: {
        model: rawRequest.model_type, // 【需适配】模型名字段
        messages: [{
          role: 'user',
          content: rawRequest.content || ''
        }], // 【需适配】消息体结构
        temperature: rawRequest.extra_param?.temperature || 0.7,
        top_p: rawRequest.extra_param?.top_p || 0.9,
        penalty_score: rawRequest.extra_param?.penalty_score || 1.0,
        stream: rawRequest.extra_param?.stream || false // 【需适配】流式开关
      }
    };
    // === 发起请求【标准代码，勿动】 ===
    try {
      const isStream = !!rawRequest.extra_param?.stream;
      // --- 流式模式 ---
      if (isStream && typeof this.httpClient.streamRequest === 'function') {
        // 【标准代码，勿动】流式回调，外层负责内容累加
        this.httpClient.streamRequest(
          requestUrl,
          requestOptions,
          (chunk) => {
            // 兼容 OpenAI/Baidu 文心流式格式：data: {...}
            let jsonStr = chunk;
            if (typeof chunk === 'string' && chunk.startsWith('data:')) {
              jsonStr = chunk.slice(5).trim();
            }
            if (jsonStr === '[DONE]') return; // 忽略结束标记
            try {
              const data = typeof jsonStr === 'string' ? JSON.parse(jsonStr) : jsonStr;
              // 【需适配】如需适配其他流式返回结构，请修改下方内容解析逻辑
              let deltaContent = '';
              if (data.choices && Array.isArray(data.choices) && data.choices[0]?.delta?.content !== undefined) {
                deltaContent = data.choices[0].delta.content;
              } else if (typeof data.result === 'string') {
                deltaContent = data.result;
              } else {
                deltaContent = '';
              }
              const done = !!(data.choices && data.choices[0]?.finish_reason === 'stop');
              callback(null, {
                completed: done,
                content: deltaContent,
                done
              });
            } catch (e) {
              // 非JSON分片可忽略
            }
          },
          () => {
            callback(null, { completed: true, done: true, content: '' });
          },
          (err) => {
            callback(err instanceof Error ? err : new Error(String(err)), null);
          }
        );
        return;
      }
      // --- 非流式模式/本地fetch流式 ---
      // 兼容主进程 httpClient 返回对象没有 .json 方法的情况【标准代码，勿动】
      const requestResult = this.httpClient.request(requestUrl, requestOptions);
      const response = await (requestResult instanceof Promise ? requestResult : Promise.resolve(requestResult));
      let data;
      if (response && typeof response.json === 'function') {
        data = await response.json();
      } else if (response && typeof response.data !== 'undefined') {
        data = response.data;
        if (typeof data === 'string') {
          try { data = JSON.parse(data); } catch (e) {}
        }
      } else {
        throw new Error('无效的响应对象');
      }
      if (!data) throw new Error('空的响应数据');
      // 新增：检测 error 字段
      if (data.error) {
        // 直接抛出错误到回调
        callback(new Error(data.error.message || 'API错误'), null);
        return;
      }
      // === 结果标准化【需适配】 ===
      // 新增：打印原始返回数据，便于排查
      console.log('[ErniePlugin] 原始返回数据:', data);
      let content = '';
      let completed = false;
      let done = false;
      // 百度API常见返回格式 result 或 choices[0].message.content
      if (data.choices && Array.isArray(data.choices) && data.choices.length > 0) {
        content = data.choices[0]?.message?.content || '';
        completed = data.choices[0]?.finish_reason === 'stop';
        done = completed;
      } else if (typeof data.result === 'string') {
        content = data.result;
        completed = !!data.is_end;
        done = completed;
      } else if (data.data && typeof data.data.result === 'string') {
        // 兼容 data.data.result 格式
        content = data.data.result;
        completed = !!data.data.is_end;
        done = completed;
      } else {
        content = typeof data === 'string' ? data : '';
      }
      // 新增：打印解析后的 content
      console.log('[ErniePlugin] 解析后的 content:', content);
      callback(null, {
        completed,
        content,
        done
      });
    } catch (error) {
      callback(error instanceof Error ? error : new Error(String(error)), null);
    }
  }
}
